#include <fstream>
#include <iostream>
#include <map>
#include <vector>
#include <string>

#include <readline/readline.h>
#include <readline/history.h>
#include <time.h>

using namespace std;

#include "ROT.h"

int showCorots(const char *unrotted, bool lowest, const char *prefix) {
	int foundItems = 0;
	time_t t1 = time(NULL);
	vector<struct preRot *> *tmp = ROT::findCorots(unrotted);
	vector<int> *quickfail = new vector<int>;
	if (tmp->size()) {
		for (vector<struct preRot *>::iterator it = tmp->begin(); it != tmp->end(); it++) {
			int qft = 0;
			int itoriglen = strlen((*it)->original);
//			if (!strncasecmp((*it)->original, unrotted, itoriglen))
//				continue;
			for (vector<int>::iterator it2 = quickfail->begin(); it2 != quickfail->end(); it2++) {
				if ((*it2) == itoriglen) {
					qft = 1;
					break;
				}
			}
			if (qft == 1)
				continue;
			if (itoriglen == strlen(unrotted)) {
				cout << prefix << " " << (*it)->original << endl;
				foundItems++;
			} else {
				int size = (prefix == NULL ? 0 : strlen(prefix)) + strlen((*it)->original) + 2;
				char *tmp2 = (char *)malloc(sizeof(char) * size);

				int offset = 0;
				if (prefix != NULL) {
					strcpy(tmp2, prefix);
					offset = strlen(prefix);
				}
				
				strncpy(&(tmp2[offset]), " ", 1);
				strcpy(&(tmp2[offset+1]), (*it)->original);

				int t1 = showCorots(&unrotted[itoriglen], false, tmp2);
				if (t1 == 0)
					quickfail->push_back(itoriglen);
				foundItems+= t1;
				
				free(tmp2);
			}
		}
	}
	if (lowest) {
		cout << time(NULL) - t1 << " seconds" << endl;
		cout << foundItems << " items" << endl;
	}
	delete quickfail;
	return foundItems;
}

void loadDictionary(char *filename) {
	ifstream wordfile;
	string line;
	int read = 0;
	
	wordfile.open(filename);
	if (wordfile.is_open()) {
		cout << "Successfully opened " << filename << " for dictionary reading." << endl;
		while (!wordfile.eof()) {
			getline(wordfile, line);
			if (line.length() <= 1) continue;
			read++;
			ROT::rotAndStore(line.c_str());
		}
		cout << "Read " << read << " entries." << endl;
		wordfile.close();
		ROT::clearCache();
	} else{
		cout << "Failed to read file." << endl;
	}
}

void doUsage() {
	cout << "Valid commands: exit, quit, read dictionary <filename>, find corot for <word>, show cache performance" << endl;
}

int main(int argc, char *argv[]) {
	char *l, *tok, *tok2;
	ifstream wordfile;
	
	for (;;) {
		l = readline("libarg> ");
		if (l)
			add_history(l);
		tok = strtok(l, " ");
		if (!tok) doUsage();
		else if (!strcmp(tok, "exit") || !strcmp(tok, "quit")) {
			free(l);
			break;
		} else if (!strcmp(tok, "read")) {
			tok = strtok(NULL, " ");
			if (!tok) doUsage();
			else if (!strcmp(tok, "dictionary")) {
				tok = strtok(NULL, " ");
				if (!tok) doUsage();
				else {
					loadDictionary(tok);
				}
			} else {
				doUsage();
			}
		} else if (!strcmp(tok, "find")) {
			tok = strtok(NULL, " ");
			if (!tok) doUsage();
			else if (!strcmp(tok, "corot")) {
				tok = strtok(NULL, " ");
				if (!tok) doUsage();
				else if (!strcmp(tok, "for")) {
					string s;
					while (tok = strtok(NULL, " "))
						s += tok;
					showCorots(s.c_str(), true, NULL);
				} else {
					doUsage();
				}
			} else {
				doUsage();
			}
		} else if (!strcmp(tok, "show")) {
			tok = strtok(NULL, " ");
			if (!tok) doUsage();
			else if (!strcmp(tok, "cache")) {
				tok = strtok(NULL, " ");
				if (!tok) doUsage();
				else if (!strcmp(tok, "performance")) {
					ROT::showStatistics();
				} else {
					doUsage();
				}
			}
		} else {
			doUsage();
		}
		free(l);
	}
}
